#include "bo3d.h"

BBDECL Ogre::Material* __stdcall o_material_Create(const char* matName, const char* group, bool isManual, const char* loader, const char* createParams)
{
	Ogre::ManualResourceLoader* mLoader = (Ogre::ManualResourceLoader*)0;
	const Ogre::NameValuePairList* mCreateParams = (Ogre::NameValuePairList*)0;
	Ogre::MaterialPtr mat;
	try
	{
		mat = Ogre::MaterialManager::getSingleton().create(matName, group, isManual, mLoader, mCreateParams);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
		
	return mat.getPointer();
}

BBDECL Ogre::Material* __stdcall o_material_clone(Ogre::Material* mat, const char* newName, bool changeGroup, const char* newGroup)
{
	Ogre::String nG = Ogre::StringUtil::BLANK;
	Ogre::Material* matclone;
	if(newGroup != NULL) nG = Ogre::String(newGroup);
	try
	{
		matclone = mat->clone(Ogre::String(newName), changeGroup, nG).getPointer();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return matclone;
}

BBDECL void __stdcall o_material_setDiffuse(Ogre::Material* mat, float red, float green, float blue, float alpha)
{
	try
	{
		mat->setDiffuse(Ogre::Real(red), Ogre::Real(green), Ogre::Real(blue), Ogre::Real(alpha));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL void __stdcall o_material_setShininess(Ogre::Material* mat, float shininess)
{
	try
	{
		mat->setShininess(Ogre::Real(shininess));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

BBDECL void __stdcall o_material_setAmbient(Ogre::Material* mat, float red, float green, float blue)
{
	try
	{
		mat->setAmbient(Ogre::Real(red), Ogre::Real(green), Ogre::Real(blue));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the specular colour reflectance properties of every Pass in every Technique. 
BBDECL void __stdcall o_material_setSpecular(Ogre::Material* mat, float red, float green, float blue, float alpha)
{
	try
	{
		mat->setSpecular(Ogre::Real(red), Ogre::Real(green), Ogre::Real(blue), Ogre::Real(alpha));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the amount of self-illumination of every Pass in every Technique. 
BBDECL void __stdcall o_material_setSelfIllumination(Ogre::Material* mat, float red, float green, float blue)
{
	try
	{
		mat->setSelfIllumination(Ogre::Real(red), Ogre::Real(green), Ogre::Real(blue));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets the point size properties for every Pass in every Technique. 
BBDECL void __stdcall o_material_setPointSize(Ogre::Material* mat, float ps)
{
	try
	{
		mat->setPointSize(Ogre::Real(ps));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets whether objects using this material will receive shadows. 
BBDECL void __stdcall o_material_setReceiveShadows(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setReceiveShadows(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// 'Compiles' this Material. 
BBDECL void __stdcall o_material_compile(Ogre::Material* mat, bool autoManageTextureUnits)
{
	try
	{
		mat->compile(autoManageTextureUnits);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Sets whether or not each Pass renders with depth-buffer checking on or not. 
BBDECL void __stdcall o_material_setDepthCheckEnabled(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setDepthCheckEnabled(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets whether or not each Pass renders with depth-buffer writing on or not. 
BBDECL void __stdcall o_material_setDepthWriteEnabled(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setDepthWriteEnabled(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets whether or not colour buffer writing is enabled for each Pass. 
BBDECL void __stdcall o_material_setColourWriteEnabled(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setColourWriteEnabled(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the culling mode for each pass based on the 'vertex winding'.
BBDECL void __stdcall o_material_setCullingMode(Ogre::Material* mat, Ogre::CullingMode mode)
{
	try
	{
		mat->setCullingMode(mode);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the manual culling mode, performed by CPU rather than hardware. 
BBDECL void __stdcall o_material_setManualCullingMode(Ogre::Material* mat, Ogre::ManualCullingMode mode)
{
	try
	{
		mat->setManualCullingMode(mode);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets whether or not dynamic lighting is enabled for every Pass. 
BBDECL void __stdcall o_material_setLightingEnabled(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setLightingEnabled(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the type of light shading required. 
BBDECL void __stdcall o_material_setShadingMode(Ogre::Material* mat, Ogre::ShadeOptions mode)
{
	try
	{
		mat->setShadingMode(mode);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the fogging mode applied to each pass. 
BBDECL void __stdcall o_material_setFog(Ogre::Material* mat, bool overrideScene, Ogre::FogMode mode, boColourValue* colour,Ogre::Real expDensity,Ogre::Real linearStart,Ogre::Real linearEnd)
{
	try
	{
		Ogre::ColourValue col;
		col.r	= colour->red;
		col.g	= colour->green;
		col.b	= colour->blue;
		col.a	= colour->alpha;

		mat->setFog(overrideScene, mode, col, expDensity, linearStart, linearEnd);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the depth bias to be used for each Pass. 
BBDECL void __stdcall o_material_setDepthBias(Ogre::Material* mat, float constantBias, float slopeScaleBias)
{
	try
	{
		mat->setDepthBias(constantBias, slopeScaleBias);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Set texture filtering for every texture unit in every Technique and Pass. 
BBDECL void __stdcall o_material_setTextureFiltering(Ogre::Material* mat, TextureFilterOptions filterType)
{
	try
	{
		mat->setTextureFiltering(filterType);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the anisotropy level to be used for all textures. 
BBDECL void __stdcall o_material_setTextureAnisotropy(Ogre::Material* mat, int maxAniso)
{
	try
	{
		mat->setTextureAnisotropy(maxAniso);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Sets the kind of blending every pass has with the existing contents of the scene. 
BBDECL void __stdcall o_material_setSceneBlending(Ogre::Material* mat, SceneBlendType sbt)
{
	try
	{
		mat->setSceneBlending(sbt);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

BBDECL const char* __stdcall o_material_getName(Ogre::Material* mat)
{
	const char* name;
	try
	{
		name = mat->getName().c_str();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	

	return name;
}

BBDECL Ogre::Technique* __stdcall o_material_getTechnique(Ogre::Material* mat, unsigned short index)
{
	Ogre::Technique* tech;
	try
	{
		tech = mat->getTechnique(index);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	

	return tech;
}

// Determines if the material has any transparency with the rest of the scene (derived from whether any Techniques say they involve transparency). 
BBDECL bool __stdcall o_material_isTransparent(Ogre::Material* mat)
{
	bool t;
	try
	{
		t = mat->isTransparent();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	

	return t;
}

// Returns whether or not objects using this material will receive shadows. 
BBDECL bool __stdcall o_material_getReceiveShadows(Ogre::Material* mat)
{
	bool t;
	try
	{
		t = mat->getReceiveShadows();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	

	return t;
}

// Sets whether objects using this material be classified as opaque to the shadow caster system. 
BBDECL void __stdcall o_material_setTransparencyCastsShadows(Ogre::Material* mat, bool enabled)
{
	try
	{
		mat->setTransparencyCastsShadows(enabled);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	
}

// Returns whether or not objects using this material be classified as opaque to the shadow caster system. 
BBDECL bool __stdcall o_material_getTransparencyCastsShadows(Ogre::Material* mat)
{
	bool t;
	try
	{
		t = mat->getTransparencyCastsShadows();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}	

	return t;
}

// Creates a new Technique for this Material. 
BBDECL Ogre::Technique* __stdcall o_material_createTechnique(Ogre::Material* mat)
{
	Ogre::Technique* tech;
	try
	{
		tech = mat->createTechnique();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return tech;
}

// Retrieves the number of techniques. 
BBDECL unsigned short __stdcall o_material_getNumTechniques(Ogre::Material* mat)
{
	unsigned short num;
	try
	{
		num = mat->getNumTechniques();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return num;
}

// Removes the technique at the given index. 
BBDECL void __stdcall o_material_removeTechnique(Ogre::Material* mat, unsigned short index)
{
	try
	{
		mat->removeTechnique(index);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Removes all the techniques in this Material. 
BBDECL void __stdcall o_material_removeAllTechniques(Ogre::Material* mat)
{
	try
	{
		mat->removeAllTechniques();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}
}

// Gets the indexed supported technique. 
BBDECL Ogre::Technique* __stdcall o_material_getSupportedTechnique(Ogre::Material* mat, unsigned short index)
{
	Ogre::Technique* tech;
	try
	{
		tech = mat->getSupportedTechnique(index);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return tech;
}

// Retrieves the number of supported techniques. 
BBDECL unsigned short __stdcall o_material_getNumSupportedTechniques(Ogre::Material* mat)
{
	unsigned short num;
	try
	{
		num = mat->getNumSupportedTechniques();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return num;
}

// Gets a string explaining why any techniques are not supported. 
BBDECL const char* __stdcall o_material_getUnsupportedTechniquesExplanation(Ogre::Material* mat)
{
	const char* exp;
	try
	{
		exp = mat->getUnsupportedTechniquesExplanation().c_str();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return exp;
}

// Gets the number of levels-of-detail this material has in the given scheme, based on Technique::setLodIndex. 
BBDECL unsigned short __stdcall o_material_getNumLodLevels(Ogre::Material* mat, unsigned short schemeIndex)
{
	unsigned short lod;
	try
	{
		lod = mat->getNumLodLevels(schemeIndex);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return lod;
}

// Gets the best supported technique. 
BBDECL Ogre::Technique* __stdcall o_material_getBestTechnique(Ogre::Material* mat, unsigned short lodIndex, const Ogre::Renderable* rend)
{
	Ogre::Technique* tech;
	try
	{
		tech = mat->getBestTechnique(lodIndex, rend);
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return tech;
}

// searches for the named technique. 
BBDECL Ogre::Technique* __stdcall o_material_getTechniqueByName(Ogre::Material* mat, const char* name)
{
	Ogre::Technique* tech;
	try
	{
		tech = mat->getTechnique(Ogre::String(name));
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return tech;
}


BBDECL Ogre::Material* __stdcall o_material_getByName(const char* matName)
{
	Ogre::Material* mat;
	Ogre::MaterialPtr res;

	try
	{
		res = Ogre::MaterialManager::getSingleton().getByName(Ogre::String(matName));
		mat = res.getPointer();
	}
	catch(Ogre::Exception &e)
	{
		std::cout << e.getDescription() << std::endl;
	}

	return mat;
}